package com.bihua.web.controller.iot;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.bihua.common.annotation.Log;
import com.bihua.common.annotation.RepeatSubmit;
import com.bihua.common.core.controller.BaseController;
import com.bihua.common.core.domain.PageQuery;
import com.bihua.common.core.domain.R;
import com.bihua.common.core.page.TableDataInfo;
import com.bihua.common.core.validate.AddGroup;
import com.bihua.common.core.validate.EditGroup;
import com.bihua.common.enums.BusinessType;
import com.bihua.common.utils.StringUtils;
import com.bihua.common.utils.poi.ExcelUtil;
import com.bihua.iot.domain.bo.DeviceBo;
import com.bihua.iot.domain.bo.DeviceLocationBo;
import com.bihua.iot.domain.vo.DeviceLocationVo;
import com.bihua.iot.domain.vo.DeviceVo;
import com.bihua.iot.enums.DeviceConnectStatus;
import com.bihua.iot.service.IDeviceLocationService;
import com.bihua.iot.service.IDeviceService;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;

/**
 * 边设备档案信息
 *
 * @author bihua
 * @date 2023-06-16
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/iot/device")
public class DeviceController extends BaseController {

    private final IDeviceService iDeviceService;
    private final IDeviceLocationService iDeviceLocationService;
    /**
     * 查询边设备档案信息列表
     */
    @SaCheckPermission("iot:device:list")
    @GetMapping("/list")
    public TableDataInfo<DeviceVo> list(DeviceBo bo, PageQuery pageQuery) {
        return iDeviceService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出边设备档案信息列表
     */
    @SaCheckPermission("iot:device:export")
    @Log(title = "边设备档案信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(DeviceBo bo, HttpServletResponse response) {
        List<DeviceVo> list = iDeviceService.queryList(bo);
        ExcelUtil.exportExcel(list, "边设备档案信息", DeviceVo.class, response);
    }

    /**
     * 获取边设备档案信息详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("iot:device:query")
    @GetMapping("/{id}")
    public R<DeviceVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        DeviceVo vo = iDeviceService.queryById(id);
        DeviceLocationBo bo = new DeviceLocationBo();
        bo.setDeviceIdentification(vo.getDeviceIdentification());
        List<DeviceLocationVo> vos = iDeviceLocationService.queryList(bo);
        if(CollectionUtils.isNotEmpty(vos)){
            vo.setLocation(vos.get(0));
        }
        return R.ok(vo);
    }

    /**
     * 新增边设备档案信息
     */
    @SaCheckPermission("iot:device:add")
    @Log(title = "边设备档案信息", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody DeviceBo bo) {
        return toAjax(iDeviceService.insertByBo(bo));
    }

    /**
     * 修改边设备档案信息
     */
    @SaCheckPermission("iot:device:edit")
    @Log(title = "边设备档案信息", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody DeviceBo bo) {
        return toAjax(iDeviceService.updateByBo(bo));
    }

    /**
     * 删除边设备档案信息
     *
     * @param ids 主键串
     */
    @SaCheckPermission("iot:device:remove")
    @Log(title = "边设备档案信息", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(iDeviceService.deleteWithValidByIds(Arrays.asList(ids), true));
    }

    /**
     * 获取设备列表对应各个状态的设备数量
     * @param bo
     * @return
     */
    @SaCheckPermission("iot:device:count")
    @Log(title = "设备数量", businessType = BusinessType.OTHER)
    @GetMapping("/listStatusCount")
    public R<Map<String, Integer>> listStatusCount(DeviceBo bo) {
        Map<String, List<DeviceVo>> connectStatusCollect = iDeviceService.queryList(bo).parallelStream().collect(Collectors.groupingBy(DeviceVo::getConnectStatus));
        Map<String , Integer> countMap = new HashMap<>();
        //统计设备在线数量
        countMap.put("onlineCount", !connectStatusCollect.isEmpty()&&!CollectionUtils.isEmpty(connectStatusCollect.get(DeviceConnectStatus.ONLINE.getValue()))?connectStatusCollect.get(DeviceConnectStatus.ONLINE.getValue()).size():0);
        //统计设备离线数量
        countMap.put("offlineCount", !connectStatusCollect.isEmpty()&&!CollectionUtils.isEmpty(connectStatusCollect.get(DeviceConnectStatus.OFFLINE.getValue()))?connectStatusCollect.get(DeviceConnectStatus.OFFLINE.getValue()).size():0);
        //统计设备初始化数量
        countMap.put("initCount", !connectStatusCollect.isEmpty()&&!CollectionUtils.isEmpty(connectStatusCollect.get(DeviceConnectStatus.INIT.getValue()))?connectStatusCollect.get(DeviceConnectStatus.INIT.getValue()).size():0);
        return R.ok(countMap);
    }

    /**
     * 校验clientId是否存在
     *
     * @param clientId
     * @return
     */
    @SaCheckPermission("iot:device:query")
    @Log(title = "设备管理", businessType = BusinessType.OTHER)
    @GetMapping(value = "/validationFindOneByClientId/{clientId}")
    public R<Void> validationFindOneByClientId(@PathVariable("clientId") String clientId) {
        if (StringUtils.isEmpty(clientId)) {
            return R.fail("clientId不可为空");
        }
        DeviceVo findOneByClientId = iDeviceService.findOneByClientId(clientId);
        if (ObjectUtil.isNull(findOneByClientId)) {
            return R.ok("clientId可用");
        }
        return R.fail("clientId已存在");
    }

    /**
     * 校验设备标识是否存在
     *
     * @param deviceIdentification
     * @return
     */
    @SaCheckPermission("iot:device:query")
    @Log(title = "设备管理", businessType = BusinessType.OTHER)
    @GetMapping(value = "/validationFindOneByDeviceIdentification/{deviceIdentification}")
    public R<Void> validationFindOneByDeviceIdentification(@PathVariable("deviceIdentification") String deviceIdentification) {
        if (StringUtils.isEmpty(deviceIdentification)) {
            return R.fail("设备标识不可为空");
        }
        DeviceVo findOneByDeviceIdentification = iDeviceService.findOneByDeviceIdentification(deviceIdentification);
        if (ObjectUtil.isNull(findOneByDeviceIdentification)) {
            return R.ok("设备标识可用");
        }
        return R.fail("设备标识已存在");
    }
    /**
     * 设备断开连接接口
     */
    @SaCheckPermission("iot:device:disconnect")
    @Log(title = "设备管理", businessType = BusinessType.OTHER)
    @PostMapping("/disconnect/{ids}")
    public R<Void> disconnect(@PathVariable Long[] ids) {
        final Boolean disconnect = iDeviceService.disconnect(ids);
        return disconnect ? R.ok("操作成功") : R.fail("操作失败");
    }
}
